home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickTime / Programming Stuff / Sample Code / Music Architecture / Mixed Bag / •QTMusic Sample Sequencer / SequencerTest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-09  |  21.9 KB  |  1,119 lines  |  [TEXT/KAHL]

  1. /*
  2.  * file: SequencerTest.c
  3.  *
  4.  * started 12 January 1992 09:34
  5.  * david van brink
  6.  *
  7.  * A starting point for BigEasy programs
  8.  *
  9.  */
  10.  
  11.  
  12. /*--------------------------
  13.     Inclusions
  14. --------------------------*/
  15.  
  16. #include <QuickDraw.h>
  17. #include <Windows.h>
  18. #include <Memory.h>
  19. #include <BDC.h>
  20. //#include <Packages.h>
  21. #include <Movies.h>
  22.  
  23. #include "BigEasy2.h"
  24. #include "BigEasyUtils.h"
  25. #include "BigEasyTextish.h"
  26. #include "BigEasyGrafish.h"
  27. #include "BigEasyDialogs.h"
  28.  
  29. #define globals
  30. #include "SequencerTest.h"
  31. #include "SequencerTest Filing.h"
  32. #include "SequencerTest Realtime.h"
  33. #include "SequencerTest Movies.h"
  34.  
  35.  
  36. /*--------------------------
  37.     Limits and Konstants
  38. --------------------------*/
  39.  
  40.  
  41. enum
  42.     {
  43.     mNew = 100,
  44.     mOpen,
  45.     mSave,
  46.  
  47.     mFirstDocOnly,
  48.     mClose,
  49.     mSaveAs,
  50.     mTestTunePlayer,
  51.     mTestTunePlayerFast,
  52.     mTestTunePlayerSlave,
  53.     mSetScale,
  54.     mMakeMIDIMovie,
  55.  
  56.     mTestTuneRate,
  57.  
  58.     mLastDocOnly,
  59.  
  60.     mLast
  61.     };
  62.  
  63. /*--------------------------
  64.     Types and globals
  65. --------------------------*/
  66.  
  67. #define kHeaderHeight 16
  68. #define kDocMargin 8
  69. #define kPip 4
  70.  
  71. #define kScorePartHeight (kPip*kScoreHeight + 1 + 3*kDocMargin)
  72.  
  73. #define SignIt(x) ( (x)?1:-1)
  74.  
  75. /*--------------------------
  76.     Prototypes
  77. --------------------------*/
  78. static void DrawDoc(short n);
  79. static void ClickDoc(short n,Point p,short mods);
  80. static void KeyDoc(short n,short key,short code, short mods);
  81. static short CloseDoc(short n);
  82. static void ActivateDoc(short n);
  83. static void DeactivateDoc(short n);
  84. static void MoveDoc(short n);
  85. static void IdleDoc(short n,Boolean front);
  86. static void LetsQuit(void);
  87. static void OpenAWindow(void);
  88. static void NewDoc(void);
  89. static void MakeWindow(void);
  90. static void About(void);
  91. static void InitVars(void);
  92.  
  93. static void PointToPip(Point p,Rect *pipRect,short *pipX,short *pipY);
  94. static void PipToRect(short pipX,short pipY,Rect *pipRect,Rect *r);
  95. static void SetPipBit(ScorePart *sp,short pipX, short pipY, Boolean x);
  96.  
  97.  
  98. static pascal Boolean MyFilterProc(DialogPtr theDialog,
  99.         EventRecord *theEvent,short *itemHit);
  100.  
  101. static void TestTuneQ1Looped(short n,short item, short ref);
  102. static void TestTuneQ1(short n,short item, short ref);
  103. static void TestTuneQ2(short n,short item, short ref);
  104. static void TestTuneQ3(short n,short item, short ref);
  105. static void TestTuneQ4(short n,short item, short ref);
  106.  
  107. static void TestTuneQ5(short n,short item, short ref);
  108. static void TestTuneGaps(short n,short item, short ref);
  109. static void TestTuneQ(short n,short item, short ref);
  110. static void TestTune(short n,short item, short ref);
  111. static void TestTuneSlave(short n,short item, short ref);
  112. static void SetScale(short n,short item, short ref);
  113. static void TilePart(ScorePart *sp,short tileSize);
  114.  
  115. /*--------------------------
  116.     Computer Programs
  117. --------------------------*/
  118.  
  119.  
  120. void DrawDoc(short n)
  121. /*
  122.  * Draws the window.
  123.  */
  124.     {
  125.     Rect r,r2;
  126.     TDoc *d;
  127.     short i,x,y;
  128.     ScorePart *sp;
  129.     short phase;
  130.  
  131.     d = &gDoc[n-kFirstDocWindow];
  132.  
  133.     GoBW();
  134.     RGBBack(50000,50000,40000);
  135.     EraseRect(&gBigRect);
  136.     GoBW();
  137.  
  138.     MoveTo(0,kHeaderHeight - 3);
  139.     Line(10000,0);
  140.     MoveTo(0,kHeaderHeight - 1);
  141.     Line(10000,0);
  142.  
  143.     MoveTo(10,kHeaderHeight - 6);
  144.     TextSize(9);
  145.     TextFont(3);
  146.     TextFace(0);
  147.     DrawString("\pQuickTime Score Length: ");
  148.     if(d->qtScore)
  149.         {
  150.         DrawNum(GetHandleSize(d->qtScore));
  151.         DrawString("\p bytes");
  152.         }
  153.  
  154.     EraseRect(&g.timeRect);
  155.     FrameRect(&g.timeRect);
  156.  
  157.     for(i = 0; i<kScoreParts; i++)
  158.         {
  159.         r = g.instrumentNameRect[i];
  160.         EraseRect(&r);
  161.         FrameRect(&r);
  162.         MoveTo(r.left + 5,r.bottom - 3);
  163.         DrawNum(i+1);
  164.         DrawString("\p. ");
  165.         DrawString(d->sr.score[i].tone.instrumentName);
  166.  
  167.         r2 = g.scoreRect[i];
  168.         EraseRect(&r2);
  169.         FrameRect(&r2);
  170.         phase = 0;
  171.         for(x = r2.top + kPipSize; x < r2.bottom-1; x += kPipSize)
  172.             {
  173.             if(phase++ % 12)
  174.                 RGBFore(50000,50000,50000);
  175.             else
  176.                 RGBFore(20000,20000,20000);
  177.             MoveTo(r2.left + 1,x);
  178.             LineTo(r2.right - 2,x);
  179.             }
  180.         phase = 1;
  181.         for(x = r2.left + kPipSize; x < r2.right-1; x += kPipSize)
  182.             {
  183.             if(phase % 16 == 0)
  184.                 RGBFore(0,0,0);
  185.             else if(phase % 8 == 0)
  186.                 RGBFore(20000,20000,20000);
  187.             else if(phase % 4 == 0)
  188.                 RGBFore(40000,40000,40000);
  189.             else
  190.                 RGBFore(50000,50000,50000);
  191.             MoveTo(x,r2.top + 1);
  192.             LineTo(x,r2.bottom - 2);
  193.             phase ++;
  194.             }
  195.  
  196.         RGBFore(20000,20000,10000);
  197.         PenSize(2,2);
  198.         MoveTo(r.right,r.top + 2);
  199.         LineTo(r.right,r2.bottom);
  200.         LineTo(r2.left + 2,r2.bottom);
  201.         GoBW();
  202.  
  203.         sp = &d->sr.score[i];
  204.         for(x = 0; x < kScoreLength; x++)
  205.             for(y = 0; y< kScoreHeight; y++)
  206.                 {
  207.                 if(GetPipBit(sp,x,y))
  208.                     {
  209.                     PipToRect(x,y,&g.scoreRect[i],&r);
  210.                     PaintRect(&r);
  211.                     }
  212.                 }
  213.         }
  214.     }
  215.  
  216.  
  217. void ClickDoc(short n,Point p,short mods)
  218.     {
  219.     short i;
  220.     Boolean x;
  221.     ScorePart *sp;
  222.     TDoc *d;
  223.     short pipX,pipY;
  224.     short lastPipX,lastPipY;
  225.     short v;
  226.     Rect r;
  227.     ComponentResult thisError;
  228.  
  229.     d = &gDoc[n-kFirstDocWindow];
  230.  
  231.     if(PtInRect(p,&g.timeRect))
  232.         {
  233.         PointToPip(p,&g.timeRect,&pipX,&pipY);        /* pipX is the time */
  234.         d->position = pipX;
  235.         DoTheHeader(d);
  236.         thisError = TuneInstant(d->tp,(unsigned long *)*(d->qtScore),pipX+1);
  237.         ShowError(thisError);
  238.         lastPipX = pipX;
  239.         while(Button())
  240.             {
  241.             GetMouse(&p);
  242.             PointToPip(p,&g.timeRect,&pipX,&pipY);        /* pipX is the time */
  243.             if(pipX != lastPipX)
  244.                 {
  245.                 thisError = TuneInstant(d->tp,(unsigned long *)*(d->qtScore),pipX+1);
  246.                 ShowError(thisError);
  247.                 lastPipX = pipX;
  248.                 }
  249.             }
  250.         thisError = TuneInstant(d->tp,0,0);
  251.         ShowError(thisError);
  252.         }
  253.  
  254.     for(i = 0; i<kScoreParts; i++)
  255.         {
  256.         sp = &d->sr.score[i];
  257.  
  258.         if(PtInRect(p,&g.scoreRect[i]))
  259.             {
  260.             if(mods & optionKey)
  261.                 {
  262.                 PointToPip(p,&g.scoreRect[i],&pipX,&pipY);
  263.  
  264.                 pipY = kNoteRangeHigh - pipY;
  265.                 NAPlayNote(g.na,d->noteChannel[i],pipY,64);
  266.                 while(StillDown());
  267.                 NAPlayNote(g.na,d->noteChannel[i],pipY,0);
  268.                 
  269.                 }
  270.             else
  271.                 {
  272.                 v = p.v;
  273.                 d->changed = true;
  274.                 PointToPip(p,&g.scoreRect[i],&lastPipX,&lastPipY);
  275.                 x = !GetPipBit(sp,lastPipX,lastPipY);
  276.                 SetPipBit(sp,lastPipX,lastPipY,x);
  277.                 PipToRect(lastPipX,lastPipY,&g.scoreRect[i],&r);
  278.                 if(x)
  279.                     PaintRect(&r);
  280.                 else
  281.                     EraseRect(&r);
  282.     
  283.                 do
  284.                     {
  285.                     GetMouse(&p);
  286.                     if(mods & shiftKey)
  287.                         p.v = v;
  288.                     PointToPip(p,&g.scoreRect[i],&pipX,&pipY);
  289.                     if(pipX != lastPipX || pipY != lastPipY)
  290.                         {
  291.                         if(pipX >= 0 && pipX < kScoreLength
  292.                                 && pipY >= 0 && pipY < kScoreHeight)
  293.                             {
  294.                             SetPipBit(sp,pipX,pipY,x);
  295.                             PipToRect(pipX,pipY,&g.scoreRect[i],&r);
  296.                             if(x)
  297.                                 PaintRect(&r);
  298.                             else
  299.                                 EraseRect(&r);
  300.                             }
  301.                         lastPipX = pipX;
  302.                         lastPipY = pipY;
  303.                         }
  304.                     } while(StillDown());
  305.                 }    /* if in score rect w/o optionkey */
  306.             d->validQTScore = false;
  307.             } /* if in score rect */
  308.         else if(PtInRect(p,&g.instrumentNameRect[i]))
  309.             {
  310.             UnrollDoc(d);
  311.  
  312.             x = NAPickInstrument(g.na,MyFilterProc,"\pNew instrument for part?",&sp->tone,
  313.                     0,0,0,0);
  314. //            x = NAPickInstrument(g.na,MyFilterProc,"\pNew instrument for part?",&sp->tone);
  315.  
  316.             #ifdef separateNoteChannel
  317.                 {
  318.                 NoteRequest nr;
  319.  
  320.                 NADisposeNoteChannel(g.na,d->noteChannel[i]);
  321.                 nr. = 2;
  322.                 nr.tone = sp->tone;            
  323.                 NoteChannel(g.na,&nr,&d->noteChannel[i]);
  324.                 }
  325.             #else
  326.                 d->validQTScore = false;
  327.                 DoTheHeader(d);
  328.             #endif
  329.  
  330.             InvalRect(&g.instrumentNameRect[i]);
  331.             d->changed = true;
  332.             }
  333.         }
  334.     FixUpMenus(d);
  335.     }
  336.  
  337.  
  338.  
  339.  
  340. pascal Boolean MyFilterProc(DialogPtr theDialog,
  341.         EventRecord *theEvent,short *itemHit)
  342.     {
  343.     GrafPort *oldPort;
  344.  
  345.     GetPort(&oldPort);
  346.     SetPort(theDialog);
  347.  
  348.     if(theEvent->what == updateEvt && (DialogPtr)theEvent->message != theDialog)
  349.             HandleUpdateEvent(theEvent);
  350.  
  351.     SetPort(oldPort);
  352.     return false;
  353.     }
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363. void PointToPip(Point p,Rect *pipRect,short *pipX,short *pipY)
  364.     {
  365.     *pipX = (p.h - pipRect->left)/kPipSize;
  366.     *pipY = (p.v - pipRect->top)/kPipSize;
  367.  
  368.     if(*pipX < 0)
  369.         *pipX = 0;
  370.     else if (*pipX >= kScoreLength)
  371.         *pipX = kScoreLength - 1;
  372.  
  373.     if(*pipY < 0)
  374.         *pipY = 0;
  375.     else if (*pipY >= kScoreHeight)
  376.         *pipY = kScoreHeight - 1;
  377.     }
  378.  
  379. void PipToRect(short pipX,short pipY,Rect *pipRect,Rect *r)
  380.     {
  381.     r->left = pipRect->left + kPipSize * pipX + 1;
  382.     r->top = pipRect->top + kPipSize * pipY + 1;
  383.  
  384.     r->right = r->left + kPipSize - 1;
  385.     r->bottom = r->top + kPipSize - 1;
  386.     }
  387.  
  388. void SetPipBit(ScorePart *sp,short pipX, short pipY, Boolean x)
  389.     {
  390.     if(pipY >= kScoreHeight || pipX >= kScoreLength)
  391.         Debugger();    /* bad input */
  392.     if(x)
  393.         sp->score[pipY][pipX/32] |= 1L<<(pipX & 31);
  394.     else
  395.         sp->score[pipY][pipX/32] &= ~(1L<<(pipX & 31));
  396.     }
  397.  
  398. Boolean GetPipBit(ScorePart *sp,short pipX, short pipY)
  399.     {
  400.     if(pipY >= kScoreHeight || pipX >= kScoreLength)
  401.         Debugger();    /* bad input */
  402.     return ((sp->score[pipY][pipX/32]) & (1L<<(pipX & 31))) != 0;
  403.     }
  404.  
  405.  
  406. void TilePart(ScorePart *sp,short tileSize)
  407.     {
  408.     short i,j;
  409.     Boolean p;
  410.  
  411.     for(i = tileSize; i < kScoreLength; i++)
  412.         for(j = 0; j < kScoreHeight; j++)
  413.             {
  414.             p = GetPipBit(sp,i%tileSize,j);
  415.             SetPipBit(sp,i,j,p);
  416.             }
  417.     }
  418.  
  419.  
  420. void KeyDoc(short n,short key,short code, short mods)
  421.     {
  422.     TDoc *d;
  423.     ComponentResult thisError;
  424.  
  425.     d = &gDoc[n-kFirstDocWindow];
  426.  
  427.     switch(key)
  428.         {
  429.         case '1':;
  430.     tileIt:
  431.             TilePart(&d->sr.score[0],16);
  432.             TilePart(&d->sr.score[1],16);
  433.             TilePart(&d->sr.score[2],16);
  434.             TilePart(&d->sr.score[3],16);
  435.             InvalRect(&gBigRect);
  436.             d->validQTScore = false;
  437.             break;
  438.  
  439.  
  440.         case 'c':    /* left arrow */
  441.             d->position = 0;
  442.             goto snippet;
  443.  
  444.         case 28:    /* left arrow */
  445.             if(mods & shiftKey)
  446.                 d->position -= 4;
  447.             else
  448.                 d->position -= 1;
  449.             goto snippet;
  450.  
  451.  
  452.         case 29:    /* right arrow */
  453.             if(mods & shiftKey)
  454.                 d->position += 4;
  455.             else
  456.                 d->position += 1;
  457.         snippet:
  458.             if(d->position < 0 || d->position > 64)
  459.                 d->position = 0;
  460.             DoTheHeader(d);
  461.             thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,
  462.                     d->position,d->position+4,kTuneStartNow,nil,0);
  463.             ShowError(thisError);
  464.             break;
  465.         }
  466.     }
  467.  
  468. short CloseDoc(short n)
  469. /*
  470.  * Close that window...
  471.  */
  472.     {
  473.     short x;
  474.     TDoc *d;
  475.     Boolean cancelSave;
  476.  
  477.     d = &gDoc[n - kFirstDocWindow];
  478.  
  479.     if(d->used && d->changed)
  480.         {
  481.         x = EasyDialogMessage(0,d->docSpec.name,"\pSave changes before closing this document?",
  482.                 kEasyDialogSaveDiscardCancel);
  483.         if(x == 2)
  484.             cancelSave = true;
  485.         else if(x == 0)
  486.             cancelSave = SaveDoc(n,0,0);
  487.         else
  488.             cancelSave = false;
  489.         }
  490.     else
  491.         cancelSave = false;
  492.  
  493.     if(!cancelSave)
  494.         {
  495.         short i;
  496.  
  497.         UninstallWindow(n);
  498.  
  499.     #ifdef separateNoteChannels
  500.         for(i = 0; i<kScoreParts; i++)
  501.             NADisposeNoteChannel(g.na,d->noteChannel[i]);
  502.     #endif
  503.  
  504.         CloseComponent(d->tp);
  505.         if(d->qtScore)
  506.             DisposeHandle(d->qtScore);
  507.  
  508.         d->used = false;
  509.         gDocCount--;
  510.         }
  511.  
  512.     return cancelSave;
  513.     }
  514.  
  515. void FixUpMenus(TDoc *d)
  516.     /*
  517.      * Make menus suitable for document d,
  518.      * where d=nil means deactivate
  519.      */
  520.     {
  521.     short moreDocs;
  522.  
  523.     moreDocs = SignIt(gDocCount<kDocMax);
  524.  
  525.     SetMenuItem(mNew,moreDocs,0,0,nil);
  526.     SetMenuItem(mOpen,moreDocs,0,0,nil);
  527.  
  528.     if(d)
  529.         {
  530.          SetMenuItem(mSave,SignIt(d->changed || d->littleChanged),0,0,nil);
  531.         SetMenuItemRange(mFirstDocOnly,mLastDocOnly,1,0);
  532.         }
  533.     else
  534.         {
  535.          SetMenuItem(mSave,-1,0,0,nil);
  536.         SetMenuItemRange(mFirstDocOnly,mLastDocOnly,-1,0);
  537.         }
  538.     }
  539.  
  540. void MoveDoc(short n)
  541.     {
  542.     TDoc *d;
  543.  
  544.     d = &gDoc[n - kFirstDocWindow];
  545.  
  546.     d->littleChanged = true;
  547.     FixUpMenus(d);
  548.     }
  549.  
  550. void ActivateDoc(short n)
  551.     {
  552.     TDoc *d;
  553.     ComponentResult thisError;
  554.  
  555.     d = &gDoc[n - kFirstDocWindow];
  556.  
  557.     thisError = TunePreroll(d->tp);
  558. //    ShowError(thisError);
  559.  
  560.     FixUpMenus(&gDoc[n - kFirstDocWindow]);
  561.     }
  562.  
  563. void DeactivateDoc(short n)
  564.     {
  565.     TDoc *d;
  566.  
  567.     d = &gDoc[n-kFirstDocWindow];
  568.     UnrollDoc(d);
  569.     FixUpMenus(nil);
  570.     }
  571.  
  572. void IdleDoc(short n,Boolean front)
  573.     {
  574.     TDoc *d;
  575.  
  576.     d = &gDoc[n-kFirstDocWindow];
  577.     }
  578.  
  579.  
  580. void UnrollDoc(TDoc *d)
  581.     {
  582.     short j;
  583.     ComponentResult thisError;
  584.  
  585. #ifdef separateNoteChannels
  586.     for(j = 0; j<kScoreParts; j++)
  587.         NAUnrollNoteChannel(g.na,d->noteChannel[j]);
  588. #endif
  589.     thisError = TuneUnroll(d->tp);
  590.     ShowError(thisError);
  591.     }
  592.  
  593.  
  594.  
  595. void LetsQuit(void)
  596.     {
  597.     short i;
  598.     TDoc *d;
  599.     short cancelQuit;
  600.  
  601.     cancelQuit = 0;
  602.  
  603.     for(i = 0; i<kDocMax; i++)
  604.         {
  605.         d = &gDoc[i];
  606.  
  607.         if(d->used)
  608.             cancelQuit |= CloseDoc(i + kFirstDocWindow);
  609.  
  610.         if(cancelQuit)
  611.             goto goHome;
  612.         }
  613.  
  614.     gQuitApp++;
  615. goHome:;
  616.     }
  617.  
  618. void NewDoc(void)
  619.     {
  620.     short i;
  621.  
  622.     for(i = 0; i<kDocMax; i++)
  623.         {
  624.         if(!gDoc[i].used)
  625.             {
  626.             NewDocFromSaveRecord(i,nil);
  627.             goto goHome;
  628.             }
  629.         }
  630. goHome:;
  631.     }
  632.  
  633.  
  634. void NewDocFromSaveRecord(short docNumber,TSaveRecord *sr)
  635.     {
  636.     TDoc *d;
  637.     Rect r;
  638.     short i;
  639.     ComponentResult thisError;
  640.  
  641.     d = &gDoc[docNumber];
  642.  
  643.     d->changed = false;
  644.  
  645.     if(sr)
  646.         {
  647.         gStaggerWindows = false;
  648.         r = sr->windowRect;
  649.  
  650.         d->everSaved = true;
  651.         d->sr = sr->sr;
  652.         d->littleChanged = false;
  653.         }
  654.     else
  655.         {
  656.         gStaggerWindows = true;
  657.         SetRect(&r,100,100,260,200);
  658.  
  659.         CopyPString(d->docSpec.name,"\pUntitled");
  660.         d->everSaved = false;
  661.         d->littleChanged = true;
  662.  
  663.         for(i = 0; i < kScoreParts; i++)
  664.             {
  665.             CopyPString(d->sr.score[i].tone.synthesizerName,"\p");
  666.             CopyPString(d->sr.score[i].tone.instrumentName,"\p");
  667.             d->sr.score[i].tone.instrumentNumber = 0;
  668.             d->sr.score[i].tone.gmNumber = 1;
  669.  
  670.                 {
  671.                 short x,y;
  672.  
  673.                 for(x = 0; x < kScoreLengthLongs; x++)
  674.                     for(y = 0; y < kScoreHeight; y++)
  675.                         d->sr.score[i].score[y][x] = 0;
  676.                 }
  677.  
  678.             }
  679.         }
  680.  
  681.     r.bottom = r.top + g.basicDocHeight;
  682.     r.right = r.left + g.basicDocWidth;
  683.  
  684.     d->w = InstallWindow(docNumber + kFirstDocWindow,d->docSpec.name,&r,0,0,
  685.             DrawDoc,ClickDoc,KeyDoc,(void *)CloseDoc,
  686.             ActivateDoc,DeactivateDoc,IdleDoc);
  687.     SetWindowMoveProc(docNumber + kFirstDocWindow,MoveDoc);
  688.     d->used = true;
  689.  
  690.  
  691.     #ifdef separateNoteChannel
  692.         {
  693.         NoteRequest nr[kScoreParts], *n;
  694.     
  695.         for(i = 0; i<kScoreParts; i++)
  696.             {
  697.             n = &nr[i];
  698.             n->polyphony = 1;
  699.             n->tone = d->sr.score[i].tone;
  700.  
  701.             thisError = NANewNoteChannel(g.na, n, &d->noteChannel[i]);
  702.             ShowError(thisError);
  703.             }
  704.         }
  705.     #endif
  706.  
  707.     d->tp = OpenDefaultComponent(kTunePlayerType,0);
  708.  
  709.     thisError = TuneSetTimeScale(d->tp,10);
  710.     ShowError(thisError);
  711.  
  712.     d->qtScore = 0;
  713.     d->validQTScore = false;
  714.     DoTheHeader(d);
  715.  
  716.     gDocCount++;
  717. goHome:;
  718.     }
  719.  
  720. void About(void)
  721.     {
  722.     EasyDialogMessage(0,(StringPtr)0x910,
  723.             "\pby David Van Brink",
  724.             kEasyDialogOkay);
  725.  
  726.     }
  727.  
  728. void InitVars(void)
  729. /*
  730.  * Called once at startup: yes, it
  731.  * inits the vars.
  732.  */
  733.     {
  734.     TDoc *dp;
  735.     short i;
  736.     Rect r;
  737.     short topBit;
  738.  
  739.     EnterMovies();
  740.  
  741.  
  742. #if 0
  743.     do
  744.         {
  745.         g.na = OpenDefaultComponent('nota',0);
  746.         CloseComponent(g.na);
  747.         } while (!Button());
  748. #endif
  749.  
  750.     g.na = OpenDefaultComponent('nota',0);
  751.  
  752.  
  753.     gDoc = (void *)NewPtrClear(kDocMax * sizeof(TDoc));
  754.     FailNil(gDoc);
  755.  
  756.     for(i = 0; i<kDocMax; i++)
  757.         {
  758.         dp = &gDoc[i];
  759.         dp->used = false;
  760.         }
  761.     gDocCount = 0;
  762.  
  763.     topBit = r.top = kHeaderHeight + kDocMargin;
  764.     r.left = kDocMargin;
  765.     for(i = 0; i<kScoreParts; i++)
  766.         {
  767.         r.right = r.left + kPipSize*kScoreLength + 1;
  768.         r.bottom = r.top + 13;
  769.         g.instrumentNameRect[i] = r;
  770.  
  771.         r.top = r.bottom - 1;
  772.         r.bottom = r.top + kPipSize*kScoreHeight + 1;
  773.         g.scoreRect[i] = r;
  774.  
  775.         if(i & 1)
  776.             {
  777.             r.top = topBit;
  778.             r.left = r.right + kDocMargin;
  779.             }
  780.         else
  781.             r.top = r.bottom + kDocMargin;
  782.         }
  783.  
  784.     g.timeRect = g.scoreRect[kScoreParts-1];
  785.     g.timeRect.top = g.timeRect.bottom + kDocMargin;
  786.     g.timeRect.bottom = g.timeRect.top + kPipSize + 1;
  787.     
  788.  
  789.     g.basicDocWidth = g.scoreRect[kScoreParts-1].right + kDocMargin;
  790.     //g.basicDocHeight = g.scoreRect[kScoreParts-1].bottom + kDocMargin;
  791.     g.basicDocHeight = g.timeRect.bottom + kDocMargin;
  792.  
  793.     }
  794.  
  795. void Bootstrap()
  796.     {
  797. /*** File Menu ***/
  798.     InstallMenu("\pFile",nil,0);
  799.     InstallMenuItem("\pNew/N",(void *)NewDoc,mNew);
  800.     InstallMenuItem("\pOpen…/O",OpenDoc,mOpen);
  801.     InstallMenuItem("\pClose/W",(void *)CloseDoc,-mClose);
  802.     InstallMenuItem("\p(-",nil,0);
  803.     InstallMenuItem("\pSave/S",(void *)SaveDoc,-mSave);
  804.     InstallMenuItem("\pSave As…",(void *)SaveAsDoc,-mSaveAs);
  805.     InstallMenuItem("\pQuit/Q",(void *)LetsQuit,0);
  806.  
  807. /*** Edit Menu ***/
  808.     InstallEditMenu(nil,nil,nil,nil,nil);
  809.  
  810. /*** Special Menu ***/
  811.     InstallMenu("\pSpecial",(void *)nil,0);
  812.     InstallMenuItem("\pMake Movie",MakeAMIDIMovie,-mMakeMIDIMovie);
  813.     InstallMenuItem("\pMake timescaled Movie",MakeAFunkyMusicMovie,-mMakeMIDIMovie);
  814.     InstallMenuItem("\p(-",nil,0);
  815.  
  816.     InstallMenuItem("\pTest Tune Looping",TestTuneQ1Looped,-mTestTunePlayer);
  817.     InstallMenuItem("\p(-",nil,0);
  818.  
  819.     InstallMenuItem("\pTest Tune Queueing/1",TestTuneQ1,-mTestTunePlayer);
  820.     InstallMenuItem("\pTest Tune Queueing/2",TestTuneQ2,-mTestTunePlayer);
  821.     InstallMenuItem("\pTest Tune Queueing/3",TestTuneQ3,-mTestTunePlayer);
  822.     InstallMenuItem("\pTest Tune Queueing/4",TestTuneQ4,-mTestTunePlayer);
  823.     InstallMenuItem("\pTest Tune Rate/5",TestTuneQ5,-mTestTunePlayer);
  824.     InstallMenuItem("\pTest Tune Gaps/6",TestTuneGaps,-mTestTunePlayer);
  825.  
  826.  
  827.     InstallMenuItem("\p(-",nil,0);
  828.  
  829.     InstallMenuItem("\pTest Fast Queueing/¡",TestTuneQ1,-mTestTunePlayerFast);
  830.     InstallMenuItem("\pTest Fast Queueing/™",TestTuneQ2,-mTestTunePlayerFast);
  831.     InstallMenuItem("\pTest Fast Queueing/£",TestTuneQ3,-mTestTunePlayerFast);
  832.     InstallMenuItem("\pTest Fast Queueing/¢",TestTuneQ4,-mTestTunePlayerFast);
  833.  
  834.     InstallMenuItem("\p(-",nil,0);
  835.  
  836.     InstallMenuItem("\pTest Tune Queueing/7",TestTuneQ,-mTestTunePlayer);
  837.     InstallMenuItem("\pTest Tune/8",TestTune,-mTestTunePlayer);
  838.     InstallMenuItem("\pTest Tune With Slave Time/9",TestTuneSlave,-mTestTunePlayerSlave);
  839.  
  840.     InstallMenuItem("\pSet Scale…",SetScale,-mSetScale);
  841.  
  842.  
  843.  
  844.         {
  845.         Str63 s;
  846.  
  847.         CopyPString(s,"\pAbout ");
  848.         ConcatenatePStrings(s,(StringPtr)0x910);
  849.         ConcatenatePStrings(s,"\p…");
  850.         SetAbout(s,0,About);
  851.         }
  852.  
  853.     SetMasterOpenDocProc(OpenDocSpec);
  854.     SetMasterQuitAppProc(LetsQuit);
  855.  
  856.     InitVars();
  857.     }
  858.  
  859. void DoTheHeader(TDoc *d)
  860.     {
  861.     short i;
  862.     ComponentResult thisError;
  863.     Handle header;
  864.  
  865.     UnrollDoc(d);
  866.  
  867.     if(!d->validQTScore)
  868.         {
  869.         ScoreToQTScore(d);
  870.         header = BuildMusicHeader(d);
  871.     
  872.         thisError = TuneSetHeader(d->tp,(unsigned long *)*header);
  873.         ShowError(thisError);
  874.  
  875.         DisposeHandle(header);
  876.  
  877.  
  878.         for(i = 0; i < kScoreParts; i++)
  879.             {
  880.             thisError = TuneGetIndexedNoteChannel(d->tp, i + 1, &d->noteChannel[i]);
  881.             ShowError(thisError);
  882.             }
  883.  
  884.  
  885.         }
  886.     }
  887.  
  888.  
  889.  
  890. void TestTune(short n,short item, short ref)
  891.     {
  892.     TDoc *d;
  893.     ComponentResult thisError;
  894.  
  895.     d = &gDoc[n - kFirstDocWindow];
  896.  
  897.     DoTheHeader(d);
  898.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,0,1000000,kTuneStartNow,nil,0);
  899.     ShowError(thisError);
  900.     }
  901.  
  902. void TestTuneQ(short n,short item, short ref)
  903.     {
  904.     TDoc *d;
  905.     ComponentResult thisError;
  906.  
  907.     d = &gDoc[n - kFirstDocWindow];
  908.  
  909.     if(!d->validQTScore)
  910.         return;
  911.  
  912.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,0,1000000,kTuneExcludeEdgeNotes,nil,0);
  913.     ShowError(thisError);
  914.     }
  915.  
  916. void TestTuneQCommon(TDoc *d,Fixed rate,short ref,long start,long stop);
  917. void TestTuneQCommon(TDoc *d,Fixed rate,short ref,long start,long stop)
  918.     {
  919.     ComponentResult thisError;
  920.  
  921.     if(!d->validQTScore)
  922.         return;
  923.  
  924.     if(rate == 0)
  925.         rate = ref == mTestTunePlayerFast ? 2*0x00010000 : 0x00010000;
  926.  
  927.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),rate,start,stop,kTuneExcludeEdgeNotes,nil,0);
  928.     ShowError(thisError);
  929.     }
  930.  
  931. void TestTuneQ1Looped(short n,short item, short ref)
  932.     {
  933.     ComponentResult thisError;
  934.     TDoc *d;
  935.  
  936.     d = &gDoc[n - kFirstDocWindow];
  937.  
  938.     if(!d->validQTScore)
  939.         return;
  940.  
  941.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,
  942.             0,16,16+kTuneExcludeEdgeNotes,nil,0);
  943.     ShowError(thisError);
  944.     }
  945.  
  946. void TestTuneQ1(short n,short item, short ref)
  947.     {
  948.     TDoc *d;
  949.  
  950.     d = &gDoc[n - kFirstDocWindow];
  951.     TestTuneQCommon(d,0,ref,0,16);
  952.     }
  953.  
  954. void TestTuneQ2(short n,short item, short ref)
  955.     {
  956.     TDoc *d;
  957.  
  958.     d = &gDoc[n - kFirstDocWindow];
  959.     TestTuneQCommon(d,0,ref,16,32);
  960.     }
  961.  
  962. void TestTuneQ3(short n,short item, short ref)
  963.     {
  964.     TDoc *d;
  965.  
  966.     d = &gDoc[n - kFirstDocWindow];
  967.     TestTuneQCommon(d,0,ref,32,48);
  968.     }
  969.  
  970. void TestTuneQ4(short n,short item, short ref)
  971.     {
  972.     TDoc *d;
  973.  
  974.     d = &gDoc[n - kFirstDocWindow];
  975.     TestTuneQCommon(d,0,ref,48,64);
  976.     }
  977.  
  978. static void TestTuneQ5(short n,short item, short ref)
  979.     {
  980.     TDoc *d;
  981.     ComponentResult thisError;
  982.  
  983.     d = &gDoc[n - kFirstDocWindow];
  984.  
  985.     if(!d->validQTScore)
  986.         return;
  987.  
  988.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,0,16,kTuneExcludeEdgeNotes,nil,0);
  989.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),2*0x00010000,16,32,kTuneExcludeEdgeNotes,nil,0);
  990.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),3*0x00010000,32,48,kTuneExcludeEdgeNotes,nil,0);
  991.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,48,64,kTuneExcludeEdgeNotes,nil,0);
  992.     ShowError(thisError);
  993.     }
  994.  
  995.  
  996. static void TestTuneGaps(short n,short item, short ref)
  997.     {
  998.     TDoc *d;
  999.     ComponentResult thisError;
  1000.  
  1001.     d = &gDoc[n - kFirstDocWindow];
  1002.  
  1003.     if(!d->validQTScore)
  1004.         return;
  1005.  
  1006.     thisError = TuneQueue(d->tp,
  1007.             0,0x00010000,0,16,kTuneExcludeEdgeNotes,nil,0);
  1008.     }
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017. void IdleSlave(long refcon);
  1018. void IdleSlave(long refcon)
  1019.     {
  1020.     TimeBase tb;
  1021.     Rect r;
  1022.  
  1023.     tb = (TimeBase)refcon;
  1024.  
  1025.     SetRect(&r,0,0,300,35);
  1026.  
  1027.     MoveTo(30,30);
  1028.     EraseRect(&r);
  1029.     DrawNum(GetTimeBaseTime(tb,1000,nil));
  1030.     }
  1031.  
  1032.  
  1033. void TestTuneSlave(short n,short item, short ref)
  1034.     {
  1035.     TDoc *d;
  1036.     TimeBase myTB,theirTB;
  1037.     ComponentInstance clock;
  1038.     Component clockComponent;
  1039.     ComponentDescription cd;
  1040.     Rect r;
  1041.     ComponentResult thisError;
  1042.  
  1043.     d = &gDoc[n - kFirstDocWindow];
  1044.  
  1045.     DoTheHeader(d);
  1046.  
  1047.     thisError = TuneGetTimeBase(d->tp,&theirTB);
  1048.     ShowError(thisError);
  1049.     clock = GetTimeBaseMasterClock(theirTB);
  1050.  
  1051.     GetComponentInfo((Component)clock,&cd,0,0,0);
  1052.     clockComponent = FindNextComponent(0,&cd);
  1053.  
  1054.     myTB = NewTimeBase();
  1055.     SetTimeBaseRate(myTB,0x00000000);
  1056.     SetTimeBaseMasterTimeBase(theirTB,myTB,0);
  1057.  
  1058.     thisError = TuneQueue(d->tp,(unsigned long *)*(d->qtScore),0x00010000,0,1000000,kTuneStartNow,nil,0);
  1059.     ShowError(thisError);
  1060.  
  1061.     EasyDialogMessage(3,
  1062.             "\pPlay Tune",
  1063.             "\pStart the tune?",
  1064.             kEasyDialogOkay);
  1065.  
  1066.     SetTimeBaseRate(myTB,0x00030000);
  1067.  
  1068.     SetRect(&r,40,100,240,200);
  1069.     EasyDialog(&r,nil,nil,nil,IdleSlave,kEasyDialogOkay,(long)theirTB);
  1070.  
  1071.     SetTimeBaseMasterClock(theirTB,clockComponent,nil);
  1072.     DisposeTimeBase(myTB);
  1073.     }
  1074.  
  1075. static void SetScale(short n,short item, short ref)
  1076.     {
  1077.     TDoc *d;
  1078.     ComponentResult thisError;
  1079.     TimeScale ts;
  1080.     Boolean x;
  1081.  
  1082.     d = &gDoc[n - kFirstDocWindow];
  1083.  
  1084.     TuneGetTimeScale(d->tp,&ts);
  1085.  
  1086.     x = EasyDialogGetNumber("\pTune Scale",
  1087.             "\pEnter the number of beats per second:",
  1088.             (long *)&ts);
  1089.  
  1090.     thisError = TuneSetTimeScale(d->tp,ts);
  1091.     }
  1092.  
  1093.  
  1094. void Hatstrap()
  1095. /*
  1096.   * clean up
  1097.   */
  1098.     {
  1099.     }
  1100.  
  1101.  
  1102. void ShowError(long error)
  1103.     {
  1104.     Str255 s1,s2,s3;
  1105.  
  1106.     if(error < 0)
  1107.         {
  1108.         AnyBaseToPString(error,16,8,s1);
  1109.         NumToString((short)(error & 0x0000FFFF),s2);
  1110.         CopyPString(s3,"\pComponent result: ");
  1111.         ConcatenatePStrings(s3,s1);
  1112.         ConcatenatePStrings(s3,"\p. Error word: ");
  1113.         ConcatenatePStrings(s3,s2);
  1114.         ConcatenatePStrings(s3,"\p.");
  1115.         EasyDialogMessage(0,"\pError",s3,kEasyDialogOkay);
  1116.         }
  1117.     }
  1118.  
  1119.